#include "stm32f10x.h"
#include "vuart2.h"
#include "delay.h"
#include <string.h>

/**
*软件串口的实现(IO模拟串口)
* 波特率：9600    1-8-N
* TXD : PE5
* RXD : PE6
* 使用外部中断对RXD的下降沿进行触发，使用定时器5按照9600波特率进行定时数据接收。
* Demo功能: 接收11个数据，然后把接收到的数据发送出去
*/




#define OI2_TXD PEout(5) //模拟TXD
#define OI2_RXD PEin(6) //模拟RXD


#define SUartLength		200            //模拟串口缓冲区长度
extern u8 SUartCnt;                    //模拟串口缓冲区位置
extern u8 SUartBuff[SUartLength];      //模拟串口缓冲区


#define BuadRate2_9600 104
#define BuadRate2_19200 52
#define BuadRate2_115200 1000000/115200

#define BuadRate BuadRate2_19200


enum {
    COM_START_BIT,
    COM_D0_BIT,
    COM_D1_BIT,
    COM_D2_BIT,
    COM_D3_BIT,
    COM_D4_BIT,
    COM_D5_BIT,
    COM_D6_BIT,
    COM_D7_BIT,
    COM_STOP_BIT,
};


u8 len = 0;	//接收计数
u8 USART_buf[30];  //接收缓冲区
u8 flag = 0; //模拟串口接收完成标记

u8 recvStat = COM_STOP_BIT;
u8 recvData = 0;

void IO2_TXD(u8 Data)
{
    u8 i = 0;
    OI2_TXD = 0;   //拉低
    Delay_us(BuadRate);
    for(i = 0; i < 8; i++)
    {
        if(Data&0x01) //LSB 低位先发
            OI2_TXD = 1;
        else
            OI2_TXD = 0;

        Delay_us(BuadRate);
        Data = Data>>1; //挨个发送
    }
    OI2_TXD = 1; //拉高
    Delay_us(BuadRate);
}

void USART2_Send(u8 *buf, u8 len2)
{
    u8 t;
    for(t = 0; t < len2; t++)
    {
        IO2_TXD(buf[t]);
    }
}

void USART2_Send_Str(u8 *str)
{
    uint32_t len = strlen((const char*)str);
    for(uint8_t i=0; i<len; i++)
    {
        IO2_TXD(str[i]);    
    }

}

void IO2Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOE, ENABLE);  //使能PB,PC端口时钟

    //SoftWare Serial TXD
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //IO口速度为50MHz
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_SetBits(GPIOE,GPIO_Pin_5);

    //SoftWare Serial RXD
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource6); //RX接收中断
    EXTI_InitStruct.EXTI_Line = EXTI_Line6;
    EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发中断 使用外部中断对RXD的下降沿进行触发，
    EXTI_InitStruct.EXTI_LineCmd=ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQn ;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void TIM5_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能

    //定时器TIM5初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
    TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
    TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); //使能指定的TIM5中断,允许更新中断


    //中断优先级NVIC设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM5中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级1级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
}

//RXD下降沿触发中断服务函数 PE6
void EXTI9_5_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line6) != RESET) //判断某个线上的中断是否发生
    {
        if(OI2_RXD == 0) //采集到低电平
        {
            if(recvStat == COM_STOP_BIT) //如果没有在发送数据
            {
                recvStat = COM_START_BIT;
                TIM_Cmd(TIM5, ENABLE); //使用定时器5按照9600波特率进行定时数据接收。
            }
        }
        EXTI_ClearITPendingBit(EXTI_Line6);
    }
}

#if 0
//定时器
void TIM5_IRQHandler(void)
{
    static u8 value=0;
	static UartState M_State = State_State;
	static u8 bit_cnt;
	
	if(TIM_GetFlagStatus(TIM5,TIM_FLAG_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM5,TIM_FLAG_Update);		
		
		if(OI2_RXD==0 && M_State == State_State)			//起始位 下降沿
		{
			M_State = State_transfer;			//接收到起始位，状态为传输中
			bit_cnt=0;
		}
		else if(M_State == State_transfer)
		{
			bit_cnt++;						
			if(OI2_RXD)
			{
				value |= (1<<(bit_cnt-1));
			}
			else 
			{
				value &= ~(1<<(bit_cnt-1));
			}
			if(bit_cnt >= 8)
				M_State = State_Stop;
		}
		else if(OI2_RXD && M_State==State_Stop)
		{
			bit_cnt=0;
			if(SUartCnt < SUartLength)
				SUartBuff[SUartCnt++] = value;			//存入缓冲区
			else 
				SUartCnt = 0;
			M_State = State_State;                      //状态回到起始状态，坐等下一帧数据
		}		
	}
}
#endif

#if 1
void TIM5_IRQHandler(void)
{
    if(TIM_GetFlagStatus(TIM5, TIM_FLAG_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
        recvStat++;
        if(recvStat == COM_STOP_BIT)
        {
            TIM_Cmd(TIM5, DISABLE);
            USART_buf[len++] = recvData;
            if(len >= 5)
            {
                flag = 1;
            }
            return;
        }
        if(OI2_RXD) //采集高电平
        {
            recvData |= (1 << (recvStat - 1));
        } else {
            recvData &= ~(1 << (recvStat - 1));
        }
    }
}
#endif



//接收串口数据处理
u8 S_Uart_Rx_Handler(u8 *buf,u8 *length)
{
	*length = 0;
	if(SUartCnt > 0)			//模拟串口缓冲区不为空
	{
		*length = SUartCnt;			
		memcpy(buf,SUartBuff,*length);		//
		
		SUartCnt = 0;
	}	
	return *length;
}

